#include "stdafx.h"
#include <cassert>
#include "actor.hpp"
#include <sfml/graphics/sprite.hpp>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include "actor_manager.hpp"


using namespace FndGame2D ;


const std::string FndGame2D::actor::ADD_FIRENDS_OR_ENEMYS("add_firends_or_enemys") ;
const std::string FndGame2D::actor::REMOVE_FIRENDS_OR_ENEMYS("remove_firends_or_enemys") ;
const std::string FndGame2D::actor::MSG_FOR_ALL_FOE("msg_for_all") ;

void FndGame2D::actor::set_center(float x, float y) {
  m_sprite->SetCenter(x,y) ;
}

void FndGame2D::actor::actor_defalut_render(sf::RenderTarget& window) 
{
    if(m_sprite)
        window.Draw(*m_sprite) ;
}
void FndGame2D::actor::change_rect(const FndGame2D::actor::key_type& key, 
				   std::size_t index) {
  const sf::IntRect& rect = m_mgr.get_value(key, index) ;
  m_sprite->SetSubRect(rect) ;
}

const actor::rect_type FndGame2D::actor::get_bounding() const 
{
    rect_type rect = m_sprite->GetSubRect() ;
    rect.Offset(get_postion().x, get_postion().y) ;
    return rect ;
}

void FndGame2D::actor::set_image(const sf::Image& img) {
  m_sprite->SetImage(img) ;
}

FndGame2D::actor::actor(const std::string& name) : 
  drawer(name),
  m_sprite(new sf::Sprite),
  m_physics(0)
{
  renderer = boost::bind(&actor::actor_defalut_render, this, _1) ;
}

void FndGame2D::actor::create_physics_obj(b2World& world, 
					  const b2BodyDef& body_def,
					  b2ShapeDef* shape_def) {
  assert(!m_physics) ;
  if(m_physics)
      return ;
  m_physics = world.CreateBody(&body_def) ;
  m_physics->CreateShape(shape_def) ;
  m_physics->SetUserData(m_sprite) ;
  m_physics->SetMassFromShapes() ;
}
float FndGame2D::actor::get_angle()const {
  assert(m_sprite != 0) ;
  return m_sprite->GetRotation() / 180.0f * 3.1415926 ;
}

void FndGame2D::actor::set_angle(float angle_in_rand) {
  assert(m_sprite) ;
  m_sprite->SetRotation(angle_in_rand * 180 / 3.1415926) ;
}

float FndGame2D::actor::get_physics_angle() const {
  assert(m_physics != 0) ;
  return m_physics->GetAngle() ;
}
const actor::position_type& FndGame2D::actor::get_postion()const {
  assert(m_sprite != 0) ;
  return m_sprite->GetPosition() ;
}

actor::position_type FndGame2D::actor::get_physics_position()const { 
  assert(m_physics != 0) ;
  return position_type(m_physics->GetPosition().x, m_physics->GetPosition().y) ;
}

void FndGame2D::actor::fix_position_use_physics() {
  assert(m_physics ) ;

  set_position(get_physics_position().x,get_physics_position().y) ;
}

void FndGame2D::actor::fix_rotation_use_physics() {
  assert(m_physics) ;
  set_angle(get_physics_angle()) ;
}

void FndGame2D::actor::set_position(float x, float y) {
  assert(m_sprite != 0) ;
  if(m_sprite == 0) return ;
  m_sprite->SetPosition(x,y) ;
}

FndGame2D::actor::~actor() {
  if(m_sprite)
    delete m_sprite ;
  m_sprite = 0 ;
  if(m_physics) {
    b2World* world = m_physics->GetWorld() ;
    world->DestroyBody(m_physics) ;
  }
  m_physics = 0 ;
}
